package com.vichat.user.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.vichat.common.cache.RedisHelper;
import com.vichat.common.constant.GlobalConstant;
import com.vichat.common.util.NumberUtils;
import com.vichat.common.vo.PageFilter;
import com.vichat.core.dao.BaseDaoI;
import com.vichat.user.entity.CcsSecFunction;
import com.vichat.user.entity.CcsSecRole;
import com.vichat.user.entity.CcsSecRoleFunction;
import com.vichat.user.entity.CcsUserSecRoleRel;
import com.vichat.user.service.ICcsSecService;
import com.vichat.user.vo.CcsSecRoleFuncVO;
import com.vichat.user.vo.Privilege;
import com.vichat.user.vo.PrivilegeVO;
import com.vichat.user.vo.RoleMenuVO;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;

/**
 * Created by user on 2017/11/15.
 */
@Service("CcsSecService")
public class CcsSecServiceImpl implements ICcsSecService {
    protected static final Logger logger = LoggerFactory.getLogger(CcsSecServiceImpl.class);
    @Autowired
    private BaseDaoI<CcsSecRole> ccsSecRoleDao;
    @Autowired
    private BaseDaoI<CcsSecFunction> ccsSecFuncDao;
    @Autowired
    private BaseDaoI<CcsSecRoleFunction> ccsSecRoleFunctionDao;
    @Autowired
    private BaseDaoI<CcsUserSecRoleRel> ccsUserSecRoleRelDao;

    /**
     * 拼装排序字段
     *
     * @param pf
     * @return
     */
    private String orderHql(PageFilter pf) {
        String orderString = "";
        if (pf != null) {
            if ((pf.getSort() != null) && (pf.getOrder() != null)) {
                orderString = " order by " + pf.getSort() + " " + pf.getOrder();
            }
        }
        return orderString;
    }

    /**
     * 查询角色信息
     *
     * @param queryBean
     * @param pf
     * @return
     */
    public List<CcsSecRole> querySecRole(CcsSecRole queryBean, PageFilter pf) {
        HashMap params = new HashMap();
        String hql = "from CcsSecRole where  state=1  ";
        if (NumberUtils.isNotNullOrZero(queryBean.getRoid())) {
            hql += " and roid = :roid";
            params.put("roid", queryBean.getRoid());
        }
        if (StringUtils.isNotBlank(queryBean.getRoleName())) {
            hql += " and roleName like :roleName";
            params.put("roleName", "%" + queryBean.getRoleName() + "%");
        }

        List<CcsSecRole> secRoles = ccsSecRoleDao.find(hql + orderHql(pf), params, pf.getPage(), pf.getLimit());
        return secRoles;
    }

    /**
     * 查询角色信息（无参数）
     *
     * @return
     */
    public List<CcsSecRole> querySecRole() {
        HashMap params = new HashMap();
        String hql = "from CcsSecRole where  state=1  ";
        hql += " order by roid";

        List<CcsSecRole> secRoles = ccsSecRoleDao.find(hql, params);
        return secRoles;
    }

    /**
     * 查询角色数量
     *
     * @param queryBean
     * @return
     * @throws Exception
     */
    public Long countSecRole(CcsSecRole queryBean) throws Exception {
        Map<String, Object> params = new HashMap<String, Object>();
        String hql = "select count(*) from CcsSecRole where state = 1";
        if (NumberUtils.isNotNullOrZero(queryBean.getRoid())) {
            hql += " and roid like :roid";
            params.put("roid", "%" + queryBean.getRoid() + "%");
        }
        if (StringUtils.isNotBlank(queryBean.getRoleName())) {
            hql += " and roleName like :roleName";
            params.put("roleName", "%" + queryBean.getRoleName() + "%");
        }
        return ccsSecRoleDao.count(hql, params);
    }

    /**
     * 根据角色编号获取角色信息
     *
     * @param roid
     * @return
     */
    public CcsSecRole querySecRoleByRoid(long roid) {
        CcsSecRole secRoleFDB = null;
        String jsonStr = RedisHelper.getCcsSecRole(roid);
        if (StringUtils.isNotBlank(jsonStr)) {
            secRoleFDB = JSONObject.parseObject(jsonStr, CcsSecRole.class);
        } else {
            if (NumberUtils.isNotNullOrZero(roid)) {
                secRoleFDB = ccsSecRoleDao.get(CcsSecRole.class, roid);
                if (secRoleFDB != null)
                    RedisHelper.setCcsSecRole(secRoleFDB.getRoid(), JSONObject.toJSONString(secRoleFDB));
            }
        }
        return secRoleFDB;
    }

    /**
     * 根据角色编号删除角色
     *
     * @param roid
     */
    public void delSecRole(long roid) {
        CcsSecRole secRoleFDB = this.querySecRoleByRoid(roid);
        if (secRoleFDB != null) {
            ccsSecRoleDao.deleted(secRoleFDB);
            RedisHelper.delCcsSecRole(roid);
        }
    }

    /**
     * 添加或者修改角色
     *
     * @param secRole
     * @throws Exception
     */
    @Override
    public void saveOrUpdSecRole(CcsSecRole secRole) throws Exception {
        CcsSecRole secRoleFDB = this.querySecRoleByRoid(secRole.getRoid());
        if (secRoleFDB == null) {
            ccsSecRoleDao.save(secRole);
            RedisHelper.setCcsSecRole(secRole.getRoid(), JSONObject.toJSONString(secRole));
        } else {
            secRoleFDB.setRoleName(secRole.getRoleName());
            secRoleFDB.setRoleDesc(secRole.getRoleDesc());
            ccsSecRoleDao.update(secRoleFDB);
            RedisHelper.setCcsSecRole(secRole.getRoid(), JSONObject.toJSONString(secRoleFDB));
        }
    }

    /**
     * 查询菜单信息
     * 无参数
     *
     * @return
     */
    public List<CcsSecFunction> querySecFunction() {
        HashMap params = new HashMap();
        String hql = "from CcsSecFunction where  state=1  ";
        hql += " order by sortno";

        List<CcsSecFunction> secFuncs = ccsSecFuncDao.find(hql, params);
        return secFuncs;
    }

    /**
     * 查询菜单信息
     *
     * @param queryBean
     * @param pf
     * @return
     */
    public List<CcsSecFunction> querySecFunction(CcsSecFunction queryBean, PageFilter pf) {
        HashMap params = new HashMap();
        String hql = "from CcsSecFunction where  state=1  ";
        if (NumberUtils.isNotNullOrZero(queryBean.getFid())) {
            hql += " and fid like :fid";
            params.put("fid", "%" + queryBean.getFid() + "%");
        }
        if (StringUtils.isNotBlank(queryBean.getFuncName())) {
            hql += " and funcName like :funcName";
            params.put("funcName", "%" + queryBean.getFuncName() + "%");
        }
        if (NumberUtils.isNotNullOrZero(queryBean.getParentFid())) {
            hql += " and ( parentFid = :parentFid or fid =:parentFid)";
            params.put("parentFid", queryBean.getParentFid());
        }
        List<CcsSecFunction> secFuncs = ccsSecFuncDao.find(hql + orderHql(pf), params, pf.getPage(), pf.getRows());
        return secFuncs;
    }

    /**
     * 查询菜单数量
     *
     * @param queryBean
     * @return
     * @throws Exception
     */

    public Long countSecFunction(CcsSecFunction queryBean) throws Exception {
        Map<String, Object> params = new HashMap<String, Object>();
        String hql = "select count(*) from CcsSecFunction where state = 1";
        if (NumberUtils.isNotNullOrZero(queryBean.getFid())) {
            hql += " and fid like :fid";
            params.put("fid", "%" + queryBean.getFid() + "%");
        }
        if (StringUtils.isNotBlank(queryBean.getFuncName())) {
            hql += " and funcName like :funcName";
            params.put("funcName", "%" + queryBean.getFuncName() + "%");
        }
        if (NumberUtils.isNotNullOrZero(queryBean.getParentFid())) {
            hql += " and ( parentFid = :parentFid or fid =:parentFid)";
            params.put("parentFid", queryBean.getParentFid());
        }
        return ccsSecFuncDao.count(hql, params);
    }

    /**
     * 根据菜单编号获取菜单信息
     *
     * @param fid
     * @return
     */
    public CcsSecFunction querySecFuncByFid(long fid) {
        CcsSecFunction secFuncFDB = null;
        String jsonStr = RedisHelper.getCcsSecFunc(fid);
        if (StringUtils.isNotBlank(jsonStr)) {
            secFuncFDB = JSONObject.parseObject(jsonStr, CcsSecFunction.class);
        } else {
            if (NumberUtils.isNotNullOrZero(fid)) {
                secFuncFDB = ccsSecFuncDao.get(CcsSecFunction.class, fid);
                RedisHelper.setCcsSecFunc(secFuncFDB.getFid(), JSONObject.toJSONString(secFuncFDB));
            }
        }
        return secFuncFDB;
    }

    /**
     * 根据角色编号获取菜单分配信息
     *
     * @param uid
     * @return
     */
    public List<CcsSecRoleFuncVO> querySecRoleFuncVOByUid(long uid) {
        List<CcsSecRoleFuncVO> secRoleFuncVOS = new ArrayList<CcsSecRoleFuncVO>();//分配菜单数据集合
        CcsSecRoleFuncVO secRoleFuncVO = null;
        HashMap params = new HashMap();

        List<CcsSecRoleFunction> secRoleFunctions = null;
        String sql = "select a.* from ccsdb.ccs_sec_role_function a,ccsdb.ccs_user b,ccsdb.ccs_user_sec_role_rel c where  a.state=1 and  a.roid = c.roid and b.ccs_uid = c.ccs_uid";
        if (NumberUtils.isNotNullOrZero(uid)) {
            sql += " and b.ccs_uid = :uid";
            params.put("uid", uid);
        }
        sql += " order by a.roid, a.fid";
        secRoleFunctions = ccsSecRoleFunctionDao.findEntityBySql(sql, params, CcsSecRoleFunction.class);
        //获取一级菜单信息
        String hql = "from CcsSecFunction where  funcType = 1 and state=1 and funcLevel =1 order by sortno";
        List<CcsSecFunction> secFirstFunctions = ccsSecFuncDao.find(hql);
        //获取二级菜单信息
        hql = "from CcsSecFunction where funcType = 1 and  state=1 and funcLevel =2 order by sortno";
        List<CcsSecFunction> secSecondFunctions = ccsSecFuncDao.find(hql);
        List<CcsSecFunction> secFuncSeconds = null;
        if (secFirstFunctions != null) {//一级菜单数据非空
            for (CcsSecFunction secFirstFunction : secFirstFunctions) {//遍历一级菜单
                secRoleFuncVO = new CcsSecRoleFuncVO();
                for (CcsSecRoleFunction secRoleFunction : secRoleFunctions) {//遍历一级菜单勾选数据
                    if (secRoleFunction.getFid().intValue() == secFirstFunction.getFid().intValue()) {
                        secFirstFunction.setIsChecked(true);
                        break;
                    }
                }
                secRoleFuncVO.setFristFunc(secFirstFunction);
                if (secSecondFunctions != null) {//二级菜单数据非空
                    secFuncSeconds = new ArrayList<>();
                    for (CcsSecFunction secSecondFunction : secSecondFunctions) {//遍历二级菜单数据
                        if (secFirstFunction.getFid().intValue() == secSecondFunction.getParentFid().intValue()) {//根据一级菜单编号筛选相关的二级菜单数据
                            for (CcsSecRoleFunction secRoleFunction : secRoleFunctions) {//遍历二级菜单勾选数据
                                if (secRoleFunction.getFid().intValue() == secSecondFunction.getFid().intValue()) {
                                    secSecondFunction.setIsChecked(true);
                                    break;
                                }
                            }
                            secFuncSeconds.add(secSecondFunction);
                        }
                    }
                    secRoleFuncVO.setSecondFuncList(secFuncSeconds);
                }
                secRoleFuncVOS.add(secRoleFuncVO);
            }
        }
        return secRoleFuncVOS;
    }

    /**
     * 根据角色编号获取菜单分配信息
     *
     * @param roid
     * @return
     */
    public List<CcsSecFunction> querySecRoleFuncVOByRoid(long roid) {
        HashMap params = new HashMap();
        String hql = "";

        List<CcsSecRoleFunction> secRoleFunctions = null;
        hql = "from CcsSecRoleFunction where  state=1  ";
        if (NumberUtils.isNotNullOrZero(roid)) {
            hql += " and roid = :roid";
            params.put("roid", roid);
        }
        hql += " order by roid, fid";
        secRoleFunctions = ccsSecRoleFunctionDao.find(hql, params);
        //获取一级菜单信息
        hql = "from CcsSecFunction where  state=1 order by sortno";
        List<CcsSecFunction> secFirstFunctions = ccsSecFuncDao.find(hql);
        if (secFirstFunctions != null) {//一级菜单数据非空
            for (CcsSecFunction secFirstFunction : secFirstFunctions) {//遍历一级菜单
                for (CcsSecRoleFunction secRoleFunction : secRoleFunctions) {//遍历一级菜单勾选数据
                    if (secRoleFunction.getFid().intValue() == secFirstFunction.getFid().intValue()) {
                        secFirstFunction.setIsChecked(true);
                        break;
                    }
                }
            }
        }
        return secFirstFunctions;
    }

    /**
     * 根据角色编号获取已勾选菜单信息
     *
     * @param roid
     * @return
     */
    public List<CcsSecRoleFunction> querySecRoleFunctionByRoid(long roid) {
        List<CcsSecRoleFunction> secRoleFuncFDBs = null;
        String jsonStr = RedisHelper.getCcsSecRoleFunc(roid);
        if (StringUtils.isNotBlank(jsonStr)) {
            secRoleFuncFDBs = JSONObject.parseArray(jsonStr, CcsSecRoleFunction.class);//获取所有已勾选的菜单
        } else {
            HashMap params = new HashMap();
            String hql = "from CcsSecRoleFunction where  state=1  ";
            if (NumberUtils.isNotNullOrZero(roid)) {
                hql += " and roid = :roid";
                params.put("roid", roid);
            }
            hql += " order by roid, fid";
            secRoleFuncFDBs = ccsSecRoleFunctionDao.find(hql, params);
        }
        return secRoleFuncFDBs;
    }

    /**
     * 增加角色名称校验
     */
    public boolean repeatSecRole(CcsSecRole queryBean) {
        Map<String, Object> params = new HashMap<String, Object>();
        String hql = "select count(*) from CcsSecRole where 1 = 1";
        if (NumberUtils.isNotNullOrZero(queryBean.getRoid())) {
            hql += " and roid <>:roid";
            params.put("roid", queryBean.getRoid());
        }
        if (StringUtils.isNotBlank(queryBean.getRoleName())) {
            hql += " and roleName =:roleName";
            params.put("roleName", queryBean.getRoleName());
        }
        long count = ccsSecRoleDao.count(hql, params);
        if (count < 1) {
            return true;
        } else {
            return false;
        }
    }

    @Override
    public void saveSecRoleFunction(RoleMenuVO roleMenuVO) {
        Long roleId = Long.parseLong(roleMenuVO.getRoleId());
        String hql = "delete from CcsSecRoleFunction where state=1 and roid=" + roleId;
        if (ccsSecRoleFunctionDao.executeHql(hql) > 0) {
            RedisHelper.delCcsSecRoleFunc(roleId);
        }
        for (String str : roleMenuVO.getList()) {
            CcsSecRoleFunction secRoleFunction = new CcsSecRoleFunction();
            secRoleFunction.setRoid(roleId);
            secRoleFunction.setFid(Long.parseLong(str));
            ccsSecRoleFunctionDao.save(secRoleFunction);
        }

        List<CcsSecRoleFunction> secRoleFuncFDBs = new ArrayList<CcsSecRoleFunction>();
        //遍历菜单时用以保存的对象
        CcsSecRoleFunction secRoleFunction = null;
        List<PrivilegeVO> privilegeVOS = new ArrayList<>();//左侧菜单
        //获取一级菜单信息
        List<CcsSecFunction> secFirstFunctions = getMenus(GlobalConstant.SEC_FUN_LEVEL_1, null);
        for (CcsSecFunction secFunction : secFirstFunctions) {
            // 保存一级菜单中勾选的数据 start
            secRoleFunction = new CcsSecRoleFunction();
            secRoleFunction.setRoid(roleId);
            secRoleFunction.setFid(secFunction.getFid());
            secRoleFuncFDBs.add(secRoleFunction);

            // 保存一级菜单中勾选的数据用做左侧菜单 start
            PrivilegeVO privilegeVO = new PrivilegeVO();
            CcsSecFunction funcNameOther = querySecFuncByFid(secFunction.getFid());
            privilegeVO.setTitle(funcNameOther.getFuncName());
            privilegeVO.setIcon(funcNameOther.getFuncPic());
            privilegeVO.setHref(funcNameOther.getFuncUrl());
            privilegeVO.setSpread(false);

            List<Privilege> privilegeSeconds = new ArrayList<>();
            //获取二级菜单信息
            List<CcsSecFunction> secSecondFunctions = getMenus(GlobalConstant.SEC_FUN_LEVEL_2, secFunction.getFid());
            for (CcsSecFunction secondFunc : secSecondFunctions) {
                // 保存二级菜单中勾选的数据 start
                secRoleFunction = new CcsSecRoleFunction();
                secRoleFunction.setRoid(roleId);
                secRoleFunction.setFid(secondFunc.getFid());

                // 保存二级菜单中勾选的数据用做左侧菜单 start
                Privilege privilegeSecond = new Privilege();
                funcNameOther = querySecFuncByFid(secondFunc.getFid());
                privilegeSecond.setTitle(funcNameOther.getFuncName());
                privilegeSecond.setIcon(funcNameOther.getFuncPic());
                privilegeSecond.setHref(funcNameOther.getFuncUrl());
                privilegeSecond.setSpread(false);
                privilegeSeconds.add(privilegeSecond);//二级菜单赋值
            }
            if (!privilegeSeconds.isEmpty()) {
                privilegeVO.setChildren(privilegeSeconds);
            }
            privilegeVOS.add(privilegeVO);

        }
        RedisHelper.setCcsSecRoleFunc(roleId, JSONObject.toJSONString(secRoleFuncFDBs));
        RedisHelper.setCcsSecPrivilege(roleId, JSONObject.toJSONString(privilegeVOS));
    }

    /**
     * @param
     * @return
     * @throws
     * @Title: getMenus
     * @Description: 获取菜单数据根据级别
     */
    public List<CcsSecFunction> getMenus(Long funcLevel, Long parentFid) {
        HashMap params = new HashMap();
        String hql = "from CcsSecFunction where state=1 ";
        if (funcLevel != null) {
            hql += " and funcLevel =:funcLevel";
            params.put("funcLevel", funcLevel);
        }
        if (parentFid != null) {
            hql += " and parentFid =:parentFid";
            params.put("parentFid", parentFid);
        }
        hql += " order by sortno";
        return ccsSecFuncDao.find(hql, params);
    }

    /**
     * 根据角色编号查询菜单
     *
     * @param uid
     * @return
     */
    public List<PrivilegeVO> querySecPrivilege(long uid) {
        List<PrivilegeVO> privilegeVOS = new ArrayList<>();
        List<CcsSecRoleFuncVO> secRoleFuncVOS = this.querySecRoleFuncVOByUid((int) uid);//获取所有菜单

        if (!secRoleFuncVOS.isEmpty()) {
            for (CcsSecRoleFuncVO secRoleFuncVO : secRoleFuncVOS) {//循环一级菜单
                if (secRoleFuncVO == null || secRoleFuncVO.getFristFunc() == null) continue;
                CcsSecFunction secFirst = secRoleFuncVO.getFristFunc();
                if (secFirst == null || !secFirst.getIsChecked()) continue;//一级有权限则赋值，否则跳到下一条
                PrivilegeVO privilegeVO = new PrivilegeVO();
                privilegeVO.setTitle(secFirst.getFuncName());
                privilegeVO.setIcon(secFirst.getFuncPic());
                privilegeVO.setHref(secFirst.getFuncUrl());
                privilegeVO.setName(secFirst.getFuncDesc());
                privilegeVO.setSpread(false);

                if (!secRoleFuncVO.getSecondFuncList().isEmpty()) {
                    List<CcsSecFunction> secSeconds = secRoleFuncVO.getSecondFuncList();
                    List<Privilege> privilegeSeconds = new ArrayList<>();
                    for (CcsSecFunction secSecond : secSeconds) {//循环二级菜单
                        if (secSecond == null || !secSecond.getIsChecked()) continue;//二级有权限则赋值，否则跳到下一条
                        Privilege privilegeSecond = new Privilege();
                        privilegeSecond.setTitle(secSecond.getFuncName());
                        privilegeSecond.setIcon(secSecond.getFuncPic());
                        privilegeSecond.setHref(secSecond.getFuncUrl());
                        privilegeSecond.setName(secSecond.getFuncDesc());
                        privilegeSecond.setSpread(false);
                        privilegeSeconds.add(privilegeSecond);//二级菜单赋值
                    }
                    if (!privilegeSeconds.isEmpty()) {
                        privilegeVO.setChildren(privilegeSeconds);
                    }
                }
                privilegeVOS.add(privilegeVO);
            }
            RedisHelper.setCcsSecPrivilege(uid, JSONObject.toJSONString(privilegeVOS));
        }
        return privilegeVOS;
    }

    /**
     * 根据条件查询角色信息
     *
     * @param uid
     * @return
     */
    public CcsSecRole querySecRoleByUid(Long uid) {
        String sql = "select a.* from ccsdb.ccs_sec_role a, ccsdb.ccs_user_sec_role_rel b where a.roid = b.roid and b.ccs_uid = :uid";
        HashMap params = new HashMap();
        params.put("uid", uid);
        List<CcsSecRole> secRoleList = ccsSecRoleDao.findEntityBySql(sql, params, CcsSecRole.class);
        if (secRoleList != null && secRoleList.size() > 0) {
            return secRoleList.get(0);
        }
        return null;
    }

    public void saveUserSecRoleRel(Long uid, Long roid) {
        //增加对应关系
        CcsUserSecRoleRel roleRole = getUserSecRoleRelByUid(uid);
        if (roleRole != null) {
            roleRole.setRoid(roid);
            roleRole.setUpdateTime(new Date());
            roleRole.setCreateTime(new Date());
            ccsUserSecRoleRelDao.update(roleRole);
        } else {
            roleRole = new CcsUserSecRoleRel();
            roleRole.setRoid(roid);
            roleRole.setCcsUid(uid);
            roleRole.setState(1L);
            roleRole.setUpdateTime(new Date());
            roleRole.setCreateTime(new Date());
            ccsUserSecRoleRelDao.save(roleRole);
        }
    }


    private CcsUserSecRoleRel getUserSecRoleRelByUid(Long uid) {
        String hql = "from CcsUserSecRoleRel where ccsUid = :uid";
        HashMap params = new HashMap();
        params.put("uid", uid);
        List<CcsUserSecRoleRel> querBeans = ccsUserSecRoleRelDao.find(hql, params);
        if (null != querBeans && querBeans.size() > 0) {
            return querBeans.get(0);
        }
        return null;
    }

    public List<CcsSecFunction> getUserEnableFunction(Long CcsUid) {
        HashMap params = new HashMap();
        String hql = "";

        List<CcsSecFunction> secRoleFunctions = null;
        hql = "select b from CcsSecRoleFunction a , CcsSecFunction b, CcsUserSecRoleRel c " +
                "where  a.state=1 and b.state =1 and c.state = 1 and a.roid = c.roid and a.fid = b.fid and c.ccsUid = :ccsUid and b.funcType = 2";
        params.put("ccsUid", CcsUid);
        secRoleFunctions = ccsSecFuncDao.find(hql, params);
        //获取一级菜单信息
        return secRoleFunctions;
    }
}
